module(..., package.seeall) -- 使得文件中的函数在何处都可调用
require "pins" -- 用到了pin库，该库为luatask专用库，需要进行引用
require "sys"
require "getLbsLoc"
require "rtos"
require "uartTask"
require "utils"
require "mqtt"
require "misc"
require "audio"
require "math"
require "nvm"
require "send433RFSignal"
require "logGenerator"
require "mqttOutMsg"
require "httpTask"
-- 初始化设备参数文件
nvm.init("config.lua", true)
-- 参数初始化 magnitude:震级
local warningColor, toneDowns, toneBreak, doToneTask, lampDowns, lampBreak,
      doLampTask, signalDowns, signalBreak, doSignalTask, sysTime, eqlog,
      errlog, alarm433Bool, ttsStr, slen, eventID, producerID, eventCancelID,
      producerCancelID, focal_longitude, focal_latitude, quake_intensity,
      quakeTimeStr, sendTime, magnitude, placeName, msgCode, actionMark,
      alertStr, isEarthquakeReport, areaCode, depth, msgID, msgSource,
      checkCode, versionAlarm, eEWID, serialNumber, recerver, warnningLevel,
      receiveTime = 0, 0, false, true, 0, false, true, 0, false, true, "", "",
                    "", false, "", string.len, "", "", "", "", 0.0, 0.0, 0.0,
                    "", "", 0.0, "", "", false, "", false, "510781006001", "",
                    "", "", "", "", "", "", "", "", ""
TTS = 1
-- 地震预警系统
-- 两个功能：1.预警系统演练（tts语音播报3遍同时报警音触发）
-- 入参：jsondata接收的预警信息
local setGpio9Fnc = pins.setup(pio.P0_9, 1) -- 静音设置（高电平静音）
local setGpio13Fnc = pins.setup(pio.P0_13, 0) -- 预警指示
local setGpio10Fnc = pins.setup(pio.P0_10, 0) -- Buzzer正常低电平，预警高电平
local setGpio17Fnc = pins.setup(pio.P0_17, 0) -- 地震预警测试音量控制，高电平为测试音量（音量小），低电平为正常音量（音量大）
-- local setGpio12Fnc = pins.setup(pio.P0_12, 0) -- 报警灯
-- 获取配置参数
local clientNo, longitude, latitude, configIntensity, enableRF433, countDown,
      alertSound, alertLight, magnitudeConfig, centerIntensityConfig,
      emergencyLamp, relay, intensityReturn, regCenter, alertVolume, blueLimit,
      yellowLimit, orangeLimit, redLimit, afterSecond, blueGuide, yellowGuide,
      orangeGuide, redGuide, exerciseText, cancelCount, clientId, answerTopic =
    nvm.get("info")[1], nvm.get("longitude"), nvm.get("latitude"),
    tonumber(nvm.get("intensity")), nvm.get("enableRF433"),
    tonumber(nvm.get("countDown")), tonumber(nvm.get("alertSound")),
    tonumber(nvm.get("alertLight")), tonumber(nvm.get("magnitude")),
    tonumber(nvm.get("centerIntensity")), tonumber(nvm.get("emergencyLamp")),
    tonumber(nvm.get("relay")), tonumber(nvm.get("intensityReturn")),
    nvm.get("regCenter"), tonumber(nvm.get("alertVolume")),
    tonumber(nvm.get("blueLimit")), tonumber(nvm.get("yellowLimit")),
    tonumber(nvm.get("orangeLimit")), tonumber(nvm.get("redLimit")),
    tonumber(nvm.get("afterSecond")), nvm.get("blueGuide"),
    nvm.get("yellowGuide"), nvm.get("orangeGuide"), nvm.get("redGuide"),
    nvm.get("exerciseText"), tonumber(nvm.get("cancelCount")),
    nvm.get("centerConfig")[6], nvm.get("centerConfig")[13]

-- 地震预警上报
local function eathquakeWarningReportHttp(distance, typeWarning, second,
                                          intensity)
    local url, sendMsg, body =
        "http://218.89.239.88:9889/externalService/receive/emergencyInformation",
        "", {}
    sendMsg = "{\n" .. "\"eventId\":" .. "\"" .. eventID .. "\"," ..
                  "\"quakeIntensity\":" .. "\"" .. quake_intensity .. "\"," ..
                  "\"distance\":" .. "\"" .. distance .. "\"," ..
                  "\"latitude\":" .. "\"" .. latitude .. "\"," .. "\"type\":" ..
                  "\"" .. typeWarning .. "\"," .. "\"quakeTime\":" .. "\"" ..
                  quakeTimeStr .. "\"," .. "\"sendTime\":" .. "\"" .. sendTime ..
                  "\"," .. "\"second\":" .. "\"" .. second .. "\"," ..
                  "\"intensity\":" .. "\"" .. intensity .. "\"," ..
                  "\"areaCode\":" .. "\"" .. areaCode .. "\"," .. "\"depth\":" ..
                  "\"" .. depth .. "\"," .. "\"location\":" .. "\"" .. placeName ..
                  "\"," .. "\"magnitude\":" .. "\"" .. magnitude .. "\"," ..
                  "\"longitude\":" .. "\"" .. longitude .. "\"}"
    body = {["dataJson"] = sendMsg}
    log.info("sendMsg", sendMsg)
    httpTask.earthquakeWarningReport(url, nil, body, 6000,
                                     "earthquakeWarningReport")
end

-- 预警事件ID组装
local function warningEventIdAssemble(quakeTimeStrGet)
    local datePre, timeSur, y, m, d, h, M, s = "", "", "", "", "", "", "", ""
    datePre = string.split(quakeTimeStrGet, " ")[1]
    timeSur = string.split(quakeTimeStrGet, " ")[2]
    y = string.split(datePre, "-")[1]
    m = string.split(datePre, "-")[2]
    d = string.split(datePre, "-")[3]
    h = string.split(timeSur, ":")[1]
    M = string.split(timeSur, ":")[2]
    s = string.split(timeSur, ":")[3]
    eventID = y .. m .. d .. h .. M .. s .. ".0001_1"
    return eventID
end

-- 获取系统时间
local function getSystemTime()
    local tClock, nowDate = os.date("*t"), ""
    local currentTime = os.time() + os.clock()
    local milliseconds = math.floor(currentTime * 1000) % 1000
    nowDate = string.format("%04d-%02d-%02d %02d:%02d:%02d", tClock.year,
                            tClock.month, tClock.day, tClock.hour, tClock.min,
                            tClock.sec)
    nowDate = nowDate .. "." .. milliseconds
    return nowDate
end
-- 发送433信号
local function send433SignalTask(countSignalDownS, intensity2F433)
    local afterSecondCount = afterSecond
    doSignalTask = false
    setGpio9Fnc(0)
    signalDowns = countSignalDownS
    send433RFSignal.InterruptSendMsg = true
    send433RFSignal.sendMsgTask()
    if not send433RFSignal.TimeId then
        send433RFSignal.signalRF433SerialCommunication(signalDowns,
                                                       intensity2F433, "0",
                                                       alarm433Bool)
    end
    sys.wait(1000)
    signalDowns = signalDowns - 1
    while signalDowns > 0 do
        if signalDowns == 1 then alarm433Bool = true end
        if not send433RFSignal.TimeId then
            send433RFSignal.signalRF433SerialCommunication(signalDowns,
                                                           intensity2F433, "0",
                                                           alarm433Bool)
        end
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        sys.wait(1000)
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        signalDowns = signalDowns - 1
    end
    while afterSecondCount > 0 do
        if not send433RFSignal.TimeId then
            send433RFSignal.signalRF433SerialCommunication(0, intensity2F433,
                                                           "0", alarm433Bool)
        end
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        sys.wait(1000)
        if signalBreak then
            signalBreak = false
            signalDowns = 0
            break
        end
        afterSecondCount = afterSecondCount - 1
    end
    setGpio9Fnc(1) -- 报警结束设置静音
    doSignalTask = true
    alarm433Bool = false
end

-- 预警声音播报任务
local function alarmVoiceTask(countDownS)
    setGpio9Fnc(0)
    -- local count = 0
    doToneTask = false
    toneDowns = countDownS
    audio.play(TTS, "TTS", alertStr, 7)
    while toneDowns > 0 do
        log.info("toneDowns", toneDowns)
        if toneDowns <= 10 then
            ttsStr = tostring(toneDowns)
            audio.play(TTS, "TTS", ttsStr, 7)
        end
        if toneBreak then
            toneBreak = false
            toneDowns = 0
            -- uartTask.write(0x0C)
            break
        end
        -- if math.fmod(count, 12) == 0 then uartTask.write(0x0C) end
        sys.wait(1000)
        if toneBreak then
            toneBreak = false
            toneDowns = 0
            -- uartTask.write(0x0C)
            break
        end
        toneDowns = toneDowns - 1
        -- count = count + 1
    end
    setGpio9Fnc(1)
    doToneTask = true
end

-- 演习或演练声音播报
local function alarmDrillVoiceTask(countDownS)
    doToneTask = false
    setGpio9Fnc(0)
    setGpio13Fnc(1)
    toneDowns = countDownS
    audio.play(TTS, "TTS", ttsStr, 7)
    while toneDowns > 0 do
        if toneDowns <= 10 then
            log.info("tts voice")
            ttsStr = tostring(toneDowns)
            audio.play(TTS, "TTS", ttsStr, 7)
        end
        -- if math.fmod(countAlarmDrill, 12) == 0 then uartTask.write(0x0C) end
        if toneBreak then
            -- uartTask.write(0x0C)
            toneBreak = false
            toneDowns = 0
            break
        end
        sys.wait(1000)
        if toneBreak then
            -- uartTask.write(0x0C)
            toneBreak = false
            toneDowns = 0
            break
        end
        toneDowns = toneDowns - 1
        -- countAlarmDrill = countAlarmDrill + 1
    end
    setGpio9Fnc(1) -- 报警结束设置静音
    setGpio17Fnc(0) -- 音量测试恢复正常（大音量）
    setGpio13Fnc(0)
    doToneTask = true
end

-- 报警灯操作任务
local function alarmLampOperationTask()
    -- local count = 0
    doLampTask = false
    lampDowns = 0
    log.info("alarmLamp enter")
    while lampDowns >= 0 and lampDowns <= 5400 do
        setGpio13Fnc(1)
        setGpio10Fnc(1)
        if lampBreak then
            lampBreak = false
            lampDowns = 0
            break
        end
        sys.wait(1000)
        if lampBreak then
            lampBreak = false
            lampDowns = 0
            break
        end
        lampDowns = lampDowns + 1
    end
    setGpio13Fnc(0)
    setGpio10Fnc(0)
    --[[ while lampDowns > 0 do
        while count ~= 4 do
            if lampBreak then
                break
            end
            setGpio12Fnc(1)
            sys.wait(125)
            setGpio12Fnc(0)
            sys.wait(125)
            count = count + 1
        end
        count = 0
        lampDowns = lampDowns - 1
        if lampBreak then
            lampBreak = false
            lampDowns = 0
            break
        end
        sys.wait(1000)
        if lampBreak then
            lampBreak = false
            lampDowns = 0
            break
        end
        lampDowns = lampDowns - 1
    end
    setGpio12Fnc(0)]]
    doLampTask = true
end

-- string转time
local function string2time(str)
    log.info("str", str)
    local dateStr, timeStr = "", ""
    dateStr = string.split(str, " ")[1]
    timeStr = string.split(str, " ")[2]
    local Y = string.split(dateStr, "-")[1]
    local m = string.split(dateStr, "-")[2]
    local d = string.split(dateStr, "-")[3]
    local H = string.split(timeStr, ":")[1]
    local M = string.split(timeStr, ":")[2]
    local S = string.split(timeStr, ":")[3]
    log.info("Y:", Y, "m:", m, "d:", d, "H:", H, "M:", M, "S:", S)
    return os.time({day = d, month = m, year = Y, hour = H, min = M, sec = S})
end

-- 烈度回传事件
local function intensityReturnTask(intensity, tjsondata, earthquakeTopic,
                                   countDownS, quakeTimeStr, focal_longitude,
                                   distance, placeName, focal_latitude)
    sysTime = getSystemTime()
    local topic = "answer"
    local sendMsg = "{" .. "\"msgLogId\":" .. tostring(intensity) ..
                        ",\"clientNo\":" .. tostring(warningColor) ..
                        ",\"info\":\"{\"1\":\"" .. tostring(tjsondata["3"]) ..
                        "\",\"2\":\"" .. tostring(tjsondata["2"]) ..
                        "\",\"3\":\"" .. sysTime .. ",\"4\":" ..
                        tostring(tjsondata["3"]) .. ",\"5\":" ..
                        string.split(earthquakeTopic, "/")[2] ..
                        "\",\"6\":\"2d89cc\",\"7\":\"1\",\"8\":\"1\",\"9\":\"" ..
                        clientNo .. "\",\"10\":\"" .. tostring(tjsondata["16"]) ..
                        "\",\"11\":\"1\"}\",\"result\":\"{'1':" .. countDownS ..
                        ",'2':" .. intensity .. ",'3':" .. warningColor ..
                        ",'4':" .. quakeTimeStr .. ",'5':" .. placeName ..
                        ",'6':" .. tostring(magnitude) .. ",'7':" .. distance ..
                        ",'8':" .. focal_longitude .. ",'9':" .. focal_latitude ..
                        ",'10':" .. longitude .. ",'11':" .. latitude ..
                        "}\",\"answerTime\":" .. os.time() * 1000 .. "}"
    sendMsg = crypto.aes_encrypt("ECB", "PKCS5", sendMsg, "keson-123abcdefg")
    sendMsg = crypto.base64_encode(sendMsg, slen(sendMsg))
    mqttOutMsg.insertMsg(topic, sendMsg, 0)
end

local function round(x)
    return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)
end

local function Algorithm(equipment_longitude, equipment_latitude,
                         focal_longitude, focal_latitude)
    local Lat1 = math.rad(equipment_latitude)
    log.info("focal_latitude:", focal_latitude)
    local Lat2 = math.rad(focal_latitude)
    local a = Lat1 - Lat2
    local b = math.rad(equipment_longitude) - math.rad(focal_longitude)
    local s = 2 *
                  math.asin(
                      math.sqrt(math.pow(math.sin(a / 2), 2) + math.cos(Lat1) *
                                    math.cos(Lat2) *
                                    math.pow(math.sin(b / 2), 2)))
    s = s * 6378137.0
    s = round(s * 10000) / 10000; -- 精确距离的数值
    return s
end

-- 烈度转换为阈值
function Intensity2Threshold(intensity2Th)
    local threhold = 0
    log.info("intensity2Th", intensity2Th, "blueLimit", blueLimit,
             "yellowLimit", yellowLimit, "redLimit", redLimit)
    if intensity2Th >= blueLimit and intensity2Th < yellowLimit then
        threhold = 1
    elseif intensity2Th >= yellowLimit and intensity2Th < orangeLimit then
        threhold = 2
    elseif intensity2Th >= orangeLimit and intensity2Th < redLimit then
        threhold = 3
    elseif intensity2Th >= redLimit then
        threhold = 4
    end
    return threhold
end

-- 预警参数组装
local function alert_parameter_assembly(tjsondata)
    if regCenter then -- 启用注册中心
        if tjsondata["2"] then -- 消息类型赋值
            msgCode = tjsondata["2"]
        end
        log.info("msgCode", msgCode)
        if "0199" == msgCode then -- 预警取消
            eventCancelID = tjsondata["7"]
            producerCancelID = tjsondata["8"]
        elseif "0101" == msgCode or "0201" == msgCode or "0301" == msgCode then -- 普通预警，普通预警演练，普通预警测试
            if tjsondata["1"] then msgID = tjsondata["1"] end -- 预警发布消息ID
            if tjsondata["2"] then msgCode = tjsondata["2"] end -- 消息类型 参考值：0101，0201，0301 0101，0201，0301
            if tjsondata["3"] then sendTime = tjsondata["3"] end -- 消息发送时间 地震发生时间，格式：YYYY-MM-DD hh:mm:ss.SSS （24小时，年-月-日 时:分：秒.毫秒）
            if tjsondata["4"] then msgSource = tjsondata["4"] end -- 来源 发布单元ID
            if tjsondata["5"] then checkCode = tjsondata["5"] end -- 校验码 用于消息体完整性、正确性校验,*后期如需要可加载数字签名
            if tjsondata["6"] then versionAlarm = tjsondata["6"] end -- 版本号 预警发布协议版本号
            if tjsondata["7"] then eEWID = tjsondata["7"] end -- 事件标识 地震事件Id
            if tjsondata["8"] then serialNumber = tjsondata["3"] end -- 序列号 地震预警事件的发布报文序号，其中：1为首报报文 255为终报
            if tjsondata["9"] then producerID = tjsondata["9"] end -- 生产者 生产单元Id，AAAAnn
            if tjsondata["10"] then recerver = tjsondata["10"] end -- 接收者 当消息类型为0201或0301时，为接收终端信息。当消息类型为其他时，此项为空。格式：“GRO:GGGnn”： GGGnn为分组groupId，分组策略由发布单元或注册中心管理；“UID:AAAAnn”:AAAAnn为接收终端ID
            if tjsondata["11"] then warnningLevel = tjsondata["11"] end -- 震中预警等级 包括：red（红色预警）、orange（橙色预警）、yellow（黄色预警）、blue（蓝色预警）
            if tjsondata["12"] then quakeTimeStr = tjsondata["12"] end -- 发震时间 地震发生时间，格式：YYYY-MM-DD hh:mm:ss.SSS （24小时，年-月-日 时:分：秒.毫秒）
            if tjsondata["13"] then placeName = tjsondata["13"] end -- 震中参考地名 Xx省xx市xx县，县级地名
            if tjsondata["14"] and tjsondata["15"] then
                focal_longitude = tonumber(tjsondata["14"]) -- 震中经度 震中经度，精度：小数点后三位，单位：度
                focal_latitude = tonumber(tjsondata["15"]) -- 震中纬度 震中纬度，精度：小数点后三位，单位：度
            end
            if tjsondata["16"] then depth = tjsondata["16"] end -- 深度 整数，单位：km
            if tjsondata["17"] then
                magnitude = tonumber(tjsondata["17"]) -- 震级 精度：一位小数
            end
            if tjsondata["18"] then
                quake_intensity = tonumber(tjsondata["18"]) -- 震中烈度 1-12之间数值，单位：度。显示时四舍五入显示。
            end
        elseif "0102" == msgCode or "0202" == msgCode or "0302" == msgCode then -- 专业预警，专业预警演练，专业预警测试
            if tjsondata["1"] then msgID = tjsondata["1"] end -- 预警发布消息ID
            if tjsondata["2"] then msgCode = tjsondata["2"] end -- 消息类型 参考值：0101，0201，0301 0101，0201，0301
            if tjsondata["3"] then sendTime = tjsondata["3"] end -- 消息发送时间 地震发生时间，格式：YYYY-MM-DD hh:mm:ss.SSS （24小时，年-月-日 时:分：秒.毫秒）
            if tjsondata["4"] then msgSource = tjsondata["4"] end -- 来源 发布单元ID
            if tjsondata["5"] then checkCode = tjsondata["5"] end -- 校验码 用于消息体完整性、正确性校验,*后期如需要可加载数字签名
            if tjsondata["6"] then versionAlarm = tjsondata["6"] end -- 版本号 预警发布协议版本号
            if tjsondata["7"] then eEWID = tjsondata["7"] end -- 事件标识 地震事件Id
            if tjsondata["12"] then sendTime = tjsondata["12"] end
            if tjsondata["16"] then placeName = tjsondata["16"] end
            if tjsondata["17"] and tjsondata["18"] then
                focal_longitude = tonumber(tjsondata["17"])
                focal_latitude = tonumber(tjsondata["18"])
            end
            if tjsondata["21"] then
                quake_intensity = tonumber(tjsondata["21"])
            end
            if tjsondata["15"] then quakeTimeStr = tjsondata["15"] end
            if tjsondata["19"] then depth = tjsondata["19"] end
            if tjsondata["20"] then
                magnitude = tonumber(tjsondata["20"])
            end
        end
    else -- keson地震预警监控平台
        if tjsondata["7"] then focal_longitude = tonumber(tjsondata["7"]) end
        if tjsondata["8"] then focal_latitude = tonumber(tjsondata["8"]) end
        if tjsondata["11"] then
            quake_intensity = tonumber(tjsondata["11"])
        end
        if tjsondata["5"] then
            quakeTimeStr = tjsondata["5"]
            eventID = warningEventIdAssemble(quakeTimeStr)
        end
        if tjsondata["10"] then magnitude = tonumber(tjsondata["10"]) end
        if tjsondata["13"] then placeName = tjsondata["13"] end
        if tjsondata["16"] then msgCode = tjsondata["16"] end
        sendTime = sysTime
        depth = "10"
    end
end

-- 预警取消
local function cancel_alert_event()
    local strAlertCancel = ""
    audio.stop()
    for i = 1, cancelCount do
        strAlertCancel = strAlertCancel .. "地震预警取消。"
    end
    audio.play(TTS, "TTS", strAlertCancel, 7)
    sys.wait(3400)
    if toneDowns > 0 then toneBreak = true end
    if lampDowns > 0 and lampDowns < 5400 then lampBreak = true end
    if signalDowns > 0 then signalBreak = true end
    while not doSignalTask do sys.wait(800) end
    if not send433RFSignal.TimeId then
        send433RFSignal.InterruptSendMsg = false
        send433RFSignal.sendMsgTask()
    end
end
-- 地震预警上报-注册中心
local function eathquakeWarningReportRegCenter(intensityLocalGet)
    local sendMsg, timeSendToIot, leds, sounds, display, threshold = "", "", "",
                                                                     "", "", 0
    timeSendToIot = getSystemTime()
    display = "no"
    threshold = Intensity2Threshold(intensityLocalGet)
    if threshold < countDown and threshold < alertSound then
        sounds = "no"
    elseif threshold >= countDown or threshold >= alertSound then
        sounds = "yes"
    end
    if intensityLocalGet >= alertLight then
        leds = "yes"
    else
        leds = "no"
    end
    if "0199" == msgCode then
        sendMsg = "{" .. "\"1\":\"" .. msgID .. "\",\"2\":\"" .. msgCode ..
                      "\",\"3\":\"" .. receiveTime .. "\",\"4\":\"" ..
                      timeSendToIot .. "\",\"5\":\"" .. clientId ..
                      "\",\"6\":\"" .. checkCode .. "\",\"7\":\"" ..
                      versionAlarm .. "\",\"8\":\"" .. eEWID .. "\",\"9\":\"" ..
                      msgSource .. "\",\"10\":{" .. "\"Leds\":" .. "\"" .. leds ..
                      "\",\"Sounds\":\"" .. sounds .. "\",\"Display\":\"" ..
                      display .. "\"}}"
    elseif "0101" == msgCode or "0201" == msgCode or "0301" == msgCode then
        sendMsg = "{\"1\":\"" .. msgID .. "\",\"2\":\"" .. msgCode ..
                      "\",\"3\":\"" .. receiveTime .. "\",\"4\":\"" ..
                      timeSendToIot .. "\",\"5\":\"" .. clientId ..
                      "\",\"6\":\"" .. checkCode .. "\",\"7\":\"" ..
                      versionAlarm .. "\",\"8\":\"" .. eEWID .. "\",\"9\":\"" ..
                      msgSource .. "\",\"10\":\"" .. warnningLevel ..
                      "\",\"11\":{" .. "\"Leds\":" .. "\"" .. leds ..
                      "\",\"Sounds\":\"" .. sounds .. "\",\"Display\":\"" ..
                      display .. "\"}}"
    elseif "0102" == msgCode or "0202" == msgCode or "0302" == msgCode then
        sendMsg = "{" .. "\"1\":\"" .. msgID .. "\",\"2\":\"" .. msgCode ..
                      "\",\"3\":\"" .. receiveTime .. "\",\"4\":\"" ..
                      timeSendToIot .. "\",\"5\":\"" .. clientId ..
                      "\",\"6\":\"" .. checkCode .. "\",\"7\":\"" ..
                      versionAlarm .. "\",\"8\":\"" .. eEWID .. "\",\"9\":" ..
                      "\"" .. msgSource .. "\",\"10\":" .. "\"" .. warnningLevel ..
                      "\"," .. "\"11\":{" .. "\"Leds\":" .. "\"" .. leds ..
                      "\",\"Sounds\":\"" .. sounds .. "\",\"Display\":\"" ..
                      display .. "\"}}"
    end
    log.info("sendMsg:", sendMsg)
    if sendMsg ~= "" then
        mqttOutMsgQuakeRel.insertQuakeRelMsg(answerTopic, sendMsg, 0)
    end
end

-- 地震预警动作执行
local function earthquake_alert_action(aesDecryptMsg, tjsondata, earthquakeTopic)
    eqlog = eqlog .. "[" .. sysTime .. "]" ..
                "接收到的地震预警消息内容:" .. "\n" .. aesDecryptMsg
    if "false" == enableRF433 then enableRF433 = false end
    if "true" == enableRF433 then enableRF433 = true end
    actionMark = true
    if toneDowns > 0 then toneBreak = true end
    if lampDowns > 0 and lampDowns < 5400 then lampBreak = true end
    if signalDowns > 0 then signalBreak = true end
    local sysTimeOs = os.time()
    log.info("sysTime", sysTimeOs, "quakeTimeStr", quakeTimeStr)
    local quakeTime = string2time(quakeTimeStr)
    log.info("quakeTime", quakeTime)
    -- 计算距离
    local distance = Algorithm(longitude, latitude, focal_longitude,
                               focal_latitude) / 1000
    log.info("distance", distance)
    -- 计算S波到达时间 减1秒网络延时
    local countDownS = math.floor((distance / 3.5) - (sysTimeOs - quakeTime))
    countDownS = countDownS < 0 and 0 or countDownS
    log.info("countDownS", countDownS)
    -- 烈度计算
    local intensityLocal = math.floor(round(
                                          quake_intensity - 4 *
                                              math.log10(distance / 10 + 1.0)))
    log.info("intensity", intensityLocal)
    if isEarthquakeReport then
        eathquakeWarningReportHttp(distance, "EEW", countDownS, distance)
    end
    if intensityLocal <= 0 then intensityLocal = 1 end
    warningColor = Intensity2Threshold(intensityLocal)
    if warningColor == 1 then
        alertStr = blueGuide .. blueGuide .. blueGuide
    elseif warningColor == 2 then
        alertStr = yellowGuide .. yellowGuide .. yellowGuide
    elseif warningColor == 3 then
        alertStr = orangeGuide .. orangeGuide .. orangeGuide
    elseif warningColor == 4 then
        alertStr = redGuide .. redGuide .. redGuide
    end
    eqlog = eqlog .. "[" .. sysTime .. "]" .. "[地震预警信息:]" ..
                "震源距离:" .. distance .. "KM,s波到达时间:" ..
                countDownS .. "s,烈度:" .. intensityLocal .. "\n"
    -- 地震烈度大于等于设定预警临界值则执行报警
    log.info("intensityLocal:", intensityLocal, "configIntensity:",
             configIntensity, "magnitude", magnitude, "magnitudeConfig",
             magnitudeConfig, "quake_intensity", quake_intensity,
             "centerIntensityConfig", centerIntensityConfig)
    if intensityLocal >= configIntensity and magnitude >= magnitudeConfig and
        quake_intensity >= centerIntensityConfig then
        eqlog = eqlog .. "[" .. sysTime .. "]" ..
                    "本地计算-达到本地预警阀值！\n"
        if countDownS > 0 then
            while not doLampTask do sys.wait(800) end
            if Intensity2Threshold(intensityLocal) >= countDown and doToneTask then
                if "0101" == msgCode or "0102" == msgCode or not regCenter then -- 普通预警，专业预警,keson转发预警
                    eqlog = eqlog .. "[" .. sysTime .. "]" ..
                                "本地计算-达到本地预警音阀值！\n"
                    sys.wait(300)
                    sys.taskInit(alarmVoiceTask, countDownS)
                    log.info("alarmVoiceTaskEND", alarmVoiceTask)
                elseif "0201" == msgCode or "0202" == msgCode then -- 普通预警演习，专业预警演习
                    ttsStr = exerciseText .. exerciseText .. exerciseText
                    sys.wait(300)
                    sys.taskInit(alarmDrillVoiceTask, countDownS)
                elseif "0301" == msgCode or "0302" == msgCode then -- 普通预警测试，专业预警测试
                    ttsStr = exerciseText .. exerciseText .. exerciseText
                    sys.wait(300)
                    sys.taskInit(alarmDrillVoiceTask, countDownS)
                end
            else
                eqlog = eqlog .. "[" .. sysTime .. "]" ..
                            "[不满足报警音临界值：]" ..
                            "烈度阈值：" ..
                            Intensity2Threshold(intensityLocal) ..
                            ",报警音预设值：" .. alertSound ..
                            "[执行报警音任务:]" .. tostring(doToneTask) ..
                            "\n"
            end
            -- 报警灯任务
            log.info("alertLight", alertLight, "intensityLocal", intensityLocal)
            if intensityLocal >= alertLight and doLampTask then
                eqlog = eqlog .. "[" .. sysTime .. "]" ..
                            "本地计算-达到本地预警灯阀值！\n"
                sys.wait(200)
                sys.taskInit(alarmLampOperationTask)
            else
                eqlog = eqlog .. "[" .. sysTime .. "]" ..
                            "[不满足报警灯临界值：]" .. "烈度：" ..
                            intensityLocal .. ",报警灯预设值：" ..
                            alertLight .. "[执行报警灯任务:]" ..
                            tostring(doLampTask) .. "\n"
            end
            while not doSignalTask do sys.wait(800) end
            -- 433信号发送任务
            if intensity2Threshold(intensityLocal) >= alertSound and enableRF433 and
                doSignalTask then
                eqlog = eqlog .. "[" .. sysTime .. "]" ..
                            "本地计算-达到本地发送433所需条件阀值！\n"
                sys.wait(200)
                sys.taskInit(send433SignalTask, countDownS, intensityLocal)
            else
                eqlog = eqlog .. "[" .. sysTime .. "]" ..
                            "[阈值，发送433，执行发送433信号存在条件不满足]" ..
                            "烈度转阈值：" ..
                            Intensity2Threshold(intensityLocal) ..
                            ",设定阈值：" .. alertSound ..
                            "是否发送灯板:" .. tostring(enableRF433) ..
                            "执行发送433信号任务" ..
                            tostring(doSignalTask) .. "\n"
            end
            while not doToneTask do sys.wait(800) end
            -- sys.taskInit(mqttQuakAlarmSendTask, intensity, countDownS)
        end
    else
        eqlog = eqlog .. "[" .. sysTime .. "]" ..
                    "[不满足预警临界值：]" .. "烈度：" ..
                    intensityLocal .. ",烈度预设值：" .. configIntensity ..
                    ",震级:" .. magnitude .. ",震级预设值:" ..
                    magnitudeConfig .. ",震中烈度:" .. quake_intensity ..
                    ",震中烈度预设值:" .. centerIntensityConfig .. "\n"
    end
    -- 烈度回传事件  科信系统
    if intensityLocal >= intensityReturn then

        log.info("intensityReturn", intensityReturn)
        intensityReturnTask(intensityLocal, tjsondata, earthquakeTopic,
                            countDownS, quakeTimeStr, focal_longitude, distance,
                            placeName, focal_latitude)
        -- sys.taskInit(intensityReturnTask, intensity, tjsondata, earthquakeTopic, countDownS, quakeTimeStr,
        --     focal_longitude, distance, placeName, focal_latitude)
    else
        eqlog = eqlog .. "[" .. sysTime .. "]" ..
                    "[不满足烈度回传临界值：]" .. "烈度：" ..
                    intensityLocal .. ",烈度回传预设值：" ..
                    intensityReturn .. "\n"
    end
    -- 其他系统预警消息返回
    if regCenter then eathquakeWarningReportRegCenter(intensityLocal) end
    actionMark = false
end

-- 地震预警主逻辑
function EarthquakeWarning(aesDecryptMsg, tjsondata, earthquakeTopic)
    receiveTime = getSystemTime()
    errlog, eqlog = "", ""
    if "true" == regCenter then
        regCenter = true
    elseif "false" == regCenter then
        regCenter = false
    end
    sysTime = getSystemTime()
    alert_parameter_assembly(tjsondata)
    log.info("Equipment_latitude", getLbsLoc.Lat, "Equipment_longitude",
             getLbsLoc.Lng)
    if longitude == "" and latitude == "" then
        longitude = getLbsLoc.Lng
        latitude = getLbsLoc.Lat
    end
    eqlog =
        eqlog .. "[" .. sysTime .. "]" .. "[设备位置信息:]" .. "Lng:" ..
            longitude .. ",Lat:" .. latitude .. "\n"
    if regCenter then -- 启用注册中心
        log.info("regCenter", regCenter)
        log.info("eventCancelID", eventCancelID, "eventID", eventID,
                 "producerID", producerID, "producerCancelID", producerCancelID)
        if "0199" == msgCode then
            if eventCancelID == eventID and producerID == producerCancelID then
                cancel_alert_event() -- 取消地震预警
            end
        else
            while actionMark do sys.wait(800) end
            sys.taskInit(earthquake_alert_action, aesDecryptMsg, tjsondata,
                         earthquakeTopic) -- 地震预警动作执行
            log.info("地震预警动作执行结束")
        end
    else -- keson转发地震预警信息
        if "0199" == msgCode or quake_intensity == 0 then
            cancel_alert_event()
        else
            while actionMark do sys.wait(800) end
            sys.taskInit(earthquake_alert_action, aesDecryptMsg, tjsondata,
                         earthquakeTopic)
        end
    end
    if eqlog ~= "" and eqlog ~= false then
        logGenerator.generateLogTask(eqlog, "eqlog")
    end
    if errlog ~= "" and errlog ~= false then
        logGenerator.generateLogTask(errlog, "errlog")
    end
end
